// Copyright (c) 1996-2002 John Lyon-Smith. All rights reserved.

#pragma once

#include <wxtl\Base.h>

using namespace boost;

namespace wxtl
{
	// Parameter parsing
	inline void _stdcall parseParams(
		const TCHAR* pParms, hash_map<tstring, tstring>& mapStrings, TCHAR *pSeps)
	{
		if (NULL == pParms)
			return;

		tstring str(pParms);

		tchar_separator sep(pSeps);
		ttokenizer tokens(str, sep);

		for (ttokenizer::iterator i = tokens.begin(); i != tokens.end(); i++)
		{
			TCHAR* pT = const_cast<TCHAR*>(_tcschr(i->c_str(), '='));
			
			if (pT != NULL)
				*pT++ = 0;
			else
				pT = _T("");

			mapStrings[*i] = pT;
		}
	}

	// HTML/XML/HTTP
	// NOTE: Currently these functions always expect ASCII characters as input.  
	enum HttpRequestType
	{
		httpGet, 
		httpPost
	};

	inline string _stdcall unencodeUrlChars(const char* p)
	{
		string str;

		// The string is at least as long as the original
		str.resize((int)strlen(p));

		char hex[3] = {0};		
		
		while (*p)
		{
			if (*p == '%')
			{
				p++;
				hex[0] = *p++;
				hex[1] = *p++;
				str += (char)strtoul(hex, NULL, 16);
			}
			else if (*p == '+')
			{
				p++;
				str += ' ';
			}
			else
			{
				str += *p++;
			}
		}

		return str;
	}

	inline void _stdcall parseHttpQuery(
		const char *pQuery, 
		hash_map<string, string>& dict)
	{
		if (NULL == pQuery)
			return;
		size_t szQueryLen = strlen(pQuery) + 1;
		char* pQueryT = new char[];
		char* p;
		char* pSeps = "&";

		dict.clear();

		strcpy_s(pQueryT,szQueryLen, pQuery);
		CHAR* chCtx;
		p = strtok_s(pQueryT, pSeps,&chCtx);

		while (p != NULL)
		{
			char* pT = strchr(p, '=');
			
			if (pT != NULL)
				*pT++ = 0;
			else
				pT = "";

			dict[p] = unencodeUrlChars(pT);

			p = strtok_s(NULL, pSeps,&chCtx);
		}

		delete [] pQueryT;
	}

	inline bool _stdcall parseHttpRequest(
		char *pHdr, size_t hdrLen, hash_map<string, string>& dict,
		HttpRequestType &requestType, string& uri, string& query, string& data)
	{	
		char *pLine = pHdr;
		char *pNext = NULL;
		char *p = NULL;
		char *q = NULL;
		size_t last = hdrLen - (sizeof(char) * 2);
		bool bFirstLine = true;

		while (true)
		{
			// Find the end of the current line, and the start of the next
			for (size_t n = 0; n <= last; n++)
			{
				if (pLine[n] == '\r' && pLine[n + 1] == '\n')
				{
					pLine[n] = 0;
					pLine[n + 1] = 0;
					pNext = pLine + n + 2;
					break;
				}
			}

			if (*pLine == 0)
			{	
				pLine = pNext;
				break;
			}

			if (bFirstLine)
			{
				p = strtok(pLine, " ");

				if (NULL == p)
					return false;

				if (stricmp(p, "GET") == 0)
					requestType = httpGet;
				else if (stricmp(p, "POST") == 0)
					requestType = httpPost;
				else
					return false;

				p = strtok(NULL, " ");

				uri = p;

				// Remove everything after the '?'
				size_t n = uri.find('?');

				if (n != -1)
				{
					query = p + n + 1;
					uri = uri.substr(0, n);
				}

				bFirstLine = false;
			}
			else
			{
				p = strtok(pLine, ":");
				q = strtok(NULL, ":");
				while (*q == ' ') 
					q++;
				dict[p] = q;
			}
		
			pLine = pNext;
		}
							
		if (requestType == httpPost)
		{
			size_t contentLen = strtoul(dict["Content-Length"].c_str(), NULL, 10);
			
			if (contentLen > 0)
				data = string(pLine, 0, (int)contentLen);
		}

		return true;
	}
}
